iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 14
0
IoT

玩玩 BLE系列 第 14

[Day 14] 分析範例程式 Simple Peripheral

  • 分享至 

  • xImage
  •  

昨天已經成功讓Simple Peripheral 在開發板上執行,
並且能夠使用手機與他進行連線,
現在我想透過手機來控制板子上的LED燈。

在實作之前先來看一下程式碼,

  • 程式的進入點 main()
  • Task 的起始點 SimplePeripheral_taskFxn()
  • 特徵值寫入時的 Callback-SimplePeripheral_processCharValueChangeEvt()

程式的進入點 main()

int main()
{
  /* 註冊協議棧的Callback */
  RegisterAssertCback(AssertHandler);

  /* 初始化腳位設置 */
  Board_initGeneral();

  // Enable iCache prefetching
  VIMSConfigure(VIMS_BASE, TRUE, TRUE);
  // Enable cache
  VIMSModeSet(VIMS_BASE, VIMS_MODE_ENABLED);

#if !defined( POWER_SAVING ) // 開啟這個預定義就會啟動省電的電源管理模式
  /* Set constraints for Standby, powerdown and idle mode */
  // PowerCC26XX_SB_DISALLOW may be redundant
  Power_setConstraint(PowerCC26XX_SB_DISALLOW);
  Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
#endif // POWER_SAVING

  /* Update User Configuration of the stack */
  user0Cfg.appServiceInfo->timerTickPeriod = Clock_tickPeriod;
  user0Cfg.appServiceInfo->timerMaxMillisecond  = ICall_getMaxMSecs();

  /* ICall允許應用程序和協議棧在TI-RTOS環境中有效率的運行、通訊和共享資源。*/
  /* Initialize ICall module */
  ICall_init();

  /* Start tasks of external images - Priority 5 */
  ICall_createRemoteTasks();

#ifdef PTM_MODE // 生產測試模式
  /* Start task for NPI task */
  NPITask_createTask(ICALL_SERVICE_CLASS_BLE);
#endif // PTM_MODE

  /* 用來開/關廣播、讀/寫特徵值和一些上層的應用邏輯 */
  SimplePeripheral_createTask();

  /* 啟用中斷以及開始執行SYS/BIOS */
  BIOS_start();

  return 0;
}

Task 的起始點 SimplePeripheral_taskFxn()

static void SimplePeripheral_taskFxn(UArg a0, UArg a1)
{
  // Task 進入無窮迴圈錢的初始化
  SimplePeripheral_init();
  // Task 的無窮迴圈
  for (;;)
  {
    // 在這邊等待事件的發生
    events = Event_pend(syncEvent, Event_Id_NONE, SP_ALL_EVENTS,
    ICALL_TIMEOUT_FOREVER);
    if (events)
    {
      ...
      // 擷取從協議棧發出的訊息
      if (ICall_fetchServiceMsg(&src, &dest,
      (void **)&pMsg) == ICALL_ERRNO_SUCCESS)
      {
        ...
        // 處理協議棧的訊息
        SimplePeripheral_processStackMsg((ICall_Hdr *)pMsg);
        ...
      }
      // 判斷是否為隊列事件(表示隊列已被排入訊息)
      if (events & SP_QUEUE_EVT)
      {
        // 一直取出隊列中的訊息,直到隊列為空
        while (!Queue_empty(appMsgQueueHandle))
        {
          spEvt_t *pMsg = (spEvt_t *)Util_dequeueMsg(appMsgQueueHandle);
          if (pMsg)
          {
            // 取出訊息並處理
            SimplePeripheral_processAppMsg(pMsg);
            ...
          }
        }
      }
    }
  }
}

特徵值寫入時的Callback SimplePeripheral_processCharValueChangeEvt()

看程式碼之前先來看一下範例程式的Characteristic有哪些,
我們直接從Lightblue來看比較快,
下圖橘框就是範例程式自定義的Service,其中共有五個Characteristic,
每個Service和Characteristic都有自己的UUID,
這邊看到的Properties有Read, Write和Notify,
Read代表這個Characteristic的值可被讀取
Write代表這個Characteristic的值可被寫入
Notify代表這個Characteristic的值被修改的時候會發出通知,但必須要先進行註冊
Service&Characteristic

// 當手機寫入任何值到藍芽裝置時,就會執行這段程式碼
// 所以當我用手機寫入0x04時,這段程式碼就會被執行
static void SimplePeripheral_processCharValueChangeEvt(uint8_t paramId)
{
  // 判斷是哪個Characteristic 被寫入,
  // SimplePeripheral只有兩個Characteristic可被寫入,
  // 所以這邊只需要判斷SIMPLEPROFILE_CHAR1或是SIMPLEPROFILE_CHAR3即可
  switch(paramId)
  {
    case SIMPLEPROFILE_CHAR1:
      // 當Characteristic 1 被寫入時,取出當前的資料
      SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
      break;
    case SIMPLEPROFILE_CHAR3:
      // 當Characteristic 3 被寫入時,取出當前的資料
      SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);
      break;
    default:
      // should not reach here!
      break;
  }
}

今天先到這邊,
明天再來點燈吧!


上一篇
[Day 13] 執行範例程式 Simple Peripheral
下一篇
[Day 15] 用手機控制LED燈
系列文
玩玩 BLE27
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言